package org.tinygame.herostory;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinygame.herostory.cmdHandler.CmdHandlerFactory;
import org.tinygame.herostory.mq.MQProducer;
import org.tinygame.herostory.util.RedisUtil;

/**
 * @author shkstart
 * @create 2022-05-04 16:34
 */
public class ServerMain {

    static private final Logger LOGGER= LoggerFactory.getLogger(ServerMain.class);
    public static void main(String[] args) {
        CmdHandlerFactory.init();
        GameMsgRecognizer.init();
        MySqlSessionFactory.init();
        RedisUtil.init();
        MQProducer.init();

        //bossGroup用于监听连接建立，workerGroup用于监听通道上的读写读写事件
        EventLoopGroup bossGroup=new NioEventLoopGroup();
        EventLoopGroup workerGroup=new NioEventLoopGroup();
        //创建服务端启动引导类：ServerBootstrap
        ServerBootstrap b = new ServerBootstrap();
        //给引导类配置两大线程组，确定io线程模型
        b.group(bossGroup,workerGroup);
        b.channel(NioServerSocketChannel.class);//服务器信道的处理方式
        b.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(
                        //自定义客户端消息的业务处理逻辑
                        new HttpServerCodec(),//http服务器编解码器
                        new HttpObjectAggregator(65535),//内容长度限制
                        new WebSocketServerProtocolHandler("/websocket"),//websocket协议处理器，处理握手ping pong等
                        new GameMsgDecoder(),//自定义的消息解码器
                        new GameMsgEncoder(),//自定义消息编码器
                        new GameMsgHandler()//自定义消息处理器
                );
            }
        });

        try{
            //绑定12345端口，调用sync方法直到绑定完成
            //项目中会使用args中的参数来指定端口号
            ChannelFuture f=b.bind(12345).sync();

            if(f.isSuccess()){
                LOGGER.info("服务器启动成功");
            }

            //阻塞等待直到服务器通道关闭
            //不会立即退出程序，让应用程序一直童工服务
            f.channel().closeFuture().sync();
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}
